package com.css.fxfzdzzh.schedule;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.css.fxfzdzzh.constants.FxfzConstants;
import com.css.fxfzdzzh.constants.YNEnum;
import com.css.fxfzdzzh.modules.basicData.param.sysDataVersion.SysDataVersionPageParam;
import com.css.fxfzdzzh.modules.basicData.service.impl.BasicLandformService;
import com.css.fxfzdzzh.modules.drill.service.DrillService;
import com.css.fxfzdzzh.modules.surfaceRupture.entity.RealEarthquakeEntity;
import com.css.fxfzdzzh.modules.surfaceRupture.entity.SurfaceRupture;
import com.css.fxfzdzzh.modules.surfaceRupture.repository.SurfaceRuptureRepository;
import com.css.fxfzdzzh.modules.surfaceRupture.service.SurfaceRuptureService;
import com.css.fxfzdzzh.modules.surfaceRupture.vo.SurfaceRuptureVO;
import com.css.fxfzdzzh.util.*;
import com.css.fxfzdzzh.web.PlatformSessionContext;
import com.css.fxfzdzzh.zcpt.sys.entity.SUser;
import com.css.fxfzdzzh.zcpt.sys.service.SUserService;
import com.css.fxfzdzzh.zcpt.sys.service.SysAreaService;
import com.css.fxfzdzzh.zcpt.sys.service.SysRoleService;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author Dbj
 * @date 2023年04月10日  15:50
 */
@Component
public class RealEarthquakeSchedule {

    @Value("${remote.address}")
    private String url;
    @Resource
    SurfaceRuptureRepository surfaceRuptureRepository;

    @Resource
    SUserService sUserService;

    @Resource
    SysAreaService sysAreaService;

    @Resource
    SurfaceRuptureService surfaceRuptureService;

    @Resource
    private DrillService drillService;


    @Value("${basicData.url}")
    public String basicDataUrl;

    @Resource
    JdbcTemplate jdbcTemplate;

    //@Scheduled(cron ="0 49 13 * * ?")
    @Scheduled(cron = "${schedule.dzzh.earthquake.cron}")
    public void getLastRealEarthquake() throws Exception{
        RealEarthquakeEntity realEarthquakeEntity = getRealEarthquakeEntity(url);

        if(realEarthquakeEntity==null){
            throw new RuntimeException("查询不到地震信息");
        }
        //经纬度
        BigDecimal longitude = realEarthquakeEntity.getLongitude();
        BigDecimal latitude = realEarthquakeEntity.getLatitude();
        Integer earthQuakeCount = surfaceRuptureRepository.getEarthQuake(longitude, latitude, realEarthquakeEntity.getTime(),"1");
        if(earthQuakeCount==0){
            //获取最新版本的活断层版本
            String faultVersion = getNewEstFaultVersion();
            if(StringUtils.isBlank(faultVersion)){
                throw new RuntimeException("获取不到最新断层版本信息");
            }
            SurfaceRuptureVO surfaceRuptureVO = new SurfaceRuptureVO();
            surfaceRuptureVO.setEarthQuakeLevel(realEarthquakeEntity.getEarthQuakeLevel());
            surfaceRuptureVO.setFaultVersion(faultVersion);
            surfaceRuptureVO.setSourceDepth(realEarthquakeEntity.getSourceDepth());
            surfaceRuptureService.createEvaluateResult(surfaceRuptureVO,longitude,latitude);
        }

    }
    /**
     * 获取活断层最新版本
     */
    private String getNewEstFaultVersion(){
        String versionCode = "";
        //固定值表示活断层
        String dataType2 = "93";
        String url = basicDataUrl + "/datacenter/sysDataVersion/list?dataType2=" + dataType2+"&dataRangeCountry=1&dataRangeProvince=-1";
        if(PlatformObjectUtils.isNotEmpty(drillService.getJCSJ(url, 3).getData())){
            JSONArray array = (JSONArray) drillService.getJCSJ(url, 3).getData();
            List<JSONObject> list = JSONObject.parseArray(array.toJSONString(),JSONObject.class);
            if(list.size()>0){
                //获取活断层最新版本
                JSONObject js = list.stream().max(Comparator.comparing(jsonObject -> jsonObject.getDate("versionTime"))).get();
                if(PlatformObjectUtils.isNotEmpty(js)){
                    versionCode = js.getString("versionCode");
                }
            }
        }
        return versionCode;
    }

    /**
     * 生成编号
     */
    private  String getTaskCode(String maxParentNum) {
        StringBuilder stringBuilder=new StringBuilder("");
        String parentNum ="";
        LocalDate date = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String format = date.format(formatter);
        stringBuilder.append(format);
        DecimalFormat decimalFormat=new DecimalFormat("000");
        if(PlatformObjectUtils.isEmpty(maxParentNum)){
            int i = 1;
            parentNum=decimalFormat.format(i);
        }else{
            String substring = maxParentNum.substring(8);
            parentNum = decimalFormat.format(Integer.parseInt(substring) + 1);
        }
        stringBuilder.append(parentNum);
        return stringBuilder.toString();
    }

    /**
     * M≥8.0级， 破裂长度区间 200-430；
     * 8.0＞M≥7.5级，破裂长度区间 60-230；
     * 7.5＞M≥7.0级，破裂长度区间 15-160；
     * 7＞M≥6.5级，破裂长度区间 0-50。
     */
    private String getCalculateLengthSection(BigDecimal ruptureLength,BigDecimal earthQuakeLevel){
        String lengthSection = "";
        BigDecimal maxSection = BigDecimal.ZERO;
        BigDecimal minSection = BigDecimal.ZERO;
        if(earthQuakeLevel.compareTo(BigDecimal.valueOf(8.0))>=0){
            BigDecimal min = ruptureLength.subtract(BigDecimal.valueOf(200));
            BigDecimal max = BigDecimal.valueOf(430).subtract(ruptureLength);
            maxSection = ruptureLength.add(min.compareTo(max) >= 0 ? max : min);
            minSection = ruptureLength.subtract(min.compareTo(max) >= 0 ? max : min);
        }else if(earthQuakeLevel.compareTo(BigDecimal.valueOf(7.5))>=0 && earthQuakeLevel.compareTo(BigDecimal.valueOf(8.0))<0){
            BigDecimal min = ruptureLength.subtract(BigDecimal.valueOf(60));
            BigDecimal max = BigDecimal.valueOf(230).subtract(ruptureLength);
            maxSection = ruptureLength.add(min.compareTo(max) >= 0 ? max : min);
            minSection = ruptureLength.subtract(min.compareTo(max) >= 0 ? max : min);
        }if(earthQuakeLevel.compareTo(BigDecimal.valueOf(7.5))<0 && earthQuakeLevel.compareTo(BigDecimal.valueOf(7.0))>=0){
            BigDecimal min = ruptureLength.subtract(BigDecimal.valueOf(15));
            BigDecimal max = BigDecimal.valueOf(160).subtract(ruptureLength);
            maxSection = ruptureLength.add(min.compareTo(max) >= 0 ? max : min);
            minSection = ruptureLength.subtract(min.compareTo(max) >= 0 ? max : min);
        }if(earthQuakeLevel.compareTo(BigDecimal.valueOf(6.5))>=0 && earthQuakeLevel.compareTo(BigDecimal.valueOf(7.0))<0){
            BigDecimal min = ruptureLength.subtract(BigDecimal.ZERO);
            BigDecimal max = BigDecimal.valueOf(50).subtract(ruptureLength);
            maxSection = ruptureLength.add(min.compareTo(max) >= 0 ? max : min);
            minSection = ruptureLength.subtract(min.compareTo(max) >= 0 ? max : min);
        }
        lengthSection = (maxSection+"_"+minSection);
        return lengthSection;
    }
    private BigDecimal getRuptureWidth(String partition, BigDecimal earthQuakeLevel) {
        //公式 ：lg地表破裂宽度=c+d*earthQuakeLevel  c和d根据地区和断层性质分别取不同的值  不在组合（地区和断层性质）范围内的不做计算
        BigDecimal c = BigDecimal.ZERO;
        BigDecimal d = BigDecimal.ZERO;
        if("中国西部".equals(partition)){
            c = BigDecimal.valueOf(-3.4318);
            d = BigDecimal.valueOf(0.6434);
        }
        if("中国东部".equals(partition)){
            c = BigDecimal.valueOf(-1.7160);
            d = BigDecimal.valueOf(0.4326);
        }
        //计算地表破裂宽度
        if(c.compareTo(BigDecimal.ZERO) ==0 && d.compareTo(BigDecimal.ZERO)==0){
            return BigDecimal.ZERO;
        }
        BigDecimal center = d.multiply(earthQuakeLevel).add(c);
        return BigDecimal.valueOf(Math.pow(10, center.doubleValue()));
    }

    private BigDecimal getDisplacement(String rupture, String partition, BigDecimal earthQuakeLevel) {
        //公式 ：lg同震位移=c+d*earthQuakeLevel  c和d根据地区和断层性质分别取不同的值  不在组合（地区和断层性质）范围内的不做计算
        BigDecimal c = BigDecimal.ZERO;
        BigDecimal d = BigDecimal.ZERO;
        if("新疆".equals(partition) && "走滑断层".equals(rupture)){
            c = BigDecimal.valueOf(-0.28);
            d = BigDecimal.valueOf(0.11);
        }
        if("青藏".equals(partition) && "走滑断层".equals(rupture)){
            c = BigDecimal.valueOf(-3.37);
            d = BigDecimal.valueOf(0.53);
        }
        if("青藏".equals(partition) && ("逆断层".equals(rupture) || "逆走滑".equals(rupture))){
            c = BigDecimal.valueOf(-6.34);
            d = BigDecimal.valueOf(0.91);
        }
        if("华北".equals(partition) && "正断层".equals(rupture)){
            c = BigDecimal.valueOf(-7.86);
            d = BigDecimal.valueOf(1.04);
        }
        //计算同震位移
        if(c.compareTo(BigDecimal.ZERO) ==0 && d.compareTo(BigDecimal.ZERO)==0){
            return BigDecimal.ZERO;
        }
        BigDecimal center = d.multiply(earthQuakeLevel).add(c);
        return BigDecimal.valueOf(Math.pow(10, center.doubleValue()));
    }

    private BiMap<String,String> buildFaultProperties(){
        BiMap<String, String> faultPropertiesMap = HashBiMap.create();
        faultPropertiesMap.put("0", "走滑断层");
        faultPropertiesMap.put("1", "逆断层");
        faultPropertiesMap.put("2", "正断层");
        faultPropertiesMap.put("3", "正走滑");
        faultPropertiesMap.put("4", "逆走滑");
        return faultPropertiesMap;
    }
    /**
     * 计算地表破裂长度
     */
    private BigDecimal getRuptureLength(String rupture, String subregion,BigDecimal earthQuakeLevel) {
        //公式 ：lg地表破裂长度=c+d*earthQuakeLevel  c和d根据地区和断层性质分别取不同的值  不在组合（地区和断层性质）范围内的不做计算
        BigDecimal c = BigDecimal.ZERO;
        BigDecimal d = BigDecimal.ZERO;
        if("新疆".equals(subregion) && "走滑断层".equals(rupture)){
            c = BigDecimal.valueOf(-4.93);
            d = BigDecimal.valueOf(0.86);
        }
        if("青藏".equals(subregion) && "走滑断层".equals(rupture)){
            c = BigDecimal.valueOf(-1.39);
            d = BigDecimal.valueOf(0.43);
        }
        if("青藏".equals(subregion) && ("逆断层".equals(rupture) || "逆走滑".equals(rupture))){
            c = BigDecimal.valueOf(-1.53);
            d = BigDecimal.valueOf(0.44);
        }
        if("华北".equals(subregion) && "正断层".equals(rupture)){
            c = BigDecimal.valueOf(-3.42);
            d = BigDecimal.valueOf(0.64);
        }
        //计算地表破裂长度L
        if(c.compareTo(BigDecimal.ZERO) ==0 && d.compareTo(BigDecimal.ZERO)==0){
            return BigDecimal.ZERO;
        }
        BigDecimal center = d.multiply(earthQuakeLevel).add(c);
        return BigDecimal.valueOf(Math.pow(10, center.doubleValue()));
    }

    /** 根据省份判断所属分区 分区与省份关系： 新疆：新疆 青藏：西藏、青海、甘肃、四川、云南、宁夏 华北：其他省份都用华北 */
    private String getSubregionByProvince(String province) {
        if(province.contains("新疆")){
            return "新疆";
        }else if(province.contains("西藏") || province.contains("青海") || province.contains("甘肃")
                ||province.contains("四川")|| province.contains("云南") || province.contains("宁夏")){
            return "青藏";
        }
        return "华北";
    }

    /** 根据省份判断所属分区 分区与省份关系： 西部：西藏、青海、甘肃、四川、云南、宁夏、新疆 东部：其他地区都用东部 */
    private String getPartitionByProvince(String province) {
        if(province.contains("西藏") || province.contains("青海") || province.contains("甘肃") || province.contains("新疆")
                ||province.contains("四川")|| province.contains("云南") || province.contains("宁夏")){
            return "中国西部";
        }
        return "中国东部";
    }

    private RealEarthquakeEntity getRealEarthquakeEntity(String url){
        String tempUrl = HttpClientUtil.doPost(url);
        JSONArray  js = (JSONArray) JSONObject.parseArray(tempUrl);
        try {
            List<RealEarthquakeEntity> list=new ArrayList<>();
            for (Object json : js) {
                JSONObject element =(JSONObject) json;
                String cataId = element.getString("CATA_ID");
                BigDecimal earthQuakeLevel = element.getBigDecimal("M");
                BigDecimal latitude =  element.getBigDecimal("EPI_LAT");
                BigDecimal longitude =  element.getBigDecimal("EPI_LON");
                if(longitude.compareTo(BigDecimal.valueOf(73.5))<0 || longitude.compareTo(BigDecimal.valueOf(135.05))>0){
                    continue;
                }
                if(latitude.compareTo(BigDecimal.valueOf(4))<0 || latitude.compareTo(BigDecimal.valueOf(53.5))>0){
                    continue;
                }
                BigDecimal sourceDepth =  element.getBigDecimal("EPI_DEPTH");
                String location = element.getString("LOCATION_C");
                Date time = element.getDate("O_TIME");
                RealEarthquakeEntity realEarthquakeEntity=new RealEarthquakeEntity(cataId,earthQuakeLevel,latitude,longitude,sourceDepth,location,time);
                list.add(realEarthquakeEntity);
            }
            RealEarthquakeEntity realEarthquakeEntity = null;
            if(list.size()>0){
                //获取最近发生的地震信息
                realEarthquakeEntity = list.stream().max(Comparator.comparing(RealEarthquakeEntity::getTime)).get();
            }
            return realEarthquakeEntity;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    //定时删除临时表
    @Scheduled(cron ="0 0 3 * * ?")
    public void dropTableRStemp(){
        String sql =  "SELECT smdatasetname FROM smregister where smdatasetname like 'RS_%'";
        List<String> tableNameList = jdbcTemplate.queryForList(sql, String.class);
        if(tableNameList!=null && tableNameList.size()>0){
            for(int i=0;i<tableNameList.size();i++){
                String tableName = tableNameList.get(i);
                String sql2 = "drop table \""+tableName+"\"";
                jdbcTemplate.update(sql2);//删除临时表
            }
            //删除超图注册表的临时表RS_
            jdbcTemplate.update("delete from smregister where smdatasetname like 'RS_%'");
        }
    }
}
